#include "Model.h"

const HashedString Model::type("Model");

Mesh::Vector_t& Model::getMeshes()
{
	return m_meshes;
}

//BindingNode::Map_t& Model::getNodes()
//{
//	return m_nodes;
//}
//
//HashedString::Vector_t& Model::getParticleSystems()
//{
//	return m_particleSystems;
//}
//
//Pointer<Skeleton>& Model::getSkeleton()
//{
//	return m_skeleton;
//}


const HashedString& Model::Type()
{
	return type;
}

const HashedString& Model::getResourceType() const
{
	return type;
}

bool Model::ToXML( tinyxml2::XMLPrinter& printer )
{
	char buffer[50];
	printer.OpenElement("Meshes");
	printer.PushAttribute("Count", m_meshes.size());

	for (Mesh::Vector_t::iterator it = m_meshes.begin(); it != m_meshes.end(); ++it)
	{
		printer.OpenElement("Mesh");
#pragma region Material
		printer.OpenElement("Material");
		
		Material& material((*it)->getMaterial());

		sprintf_s(buffer, 50, "%.3f %.3f %.3f %.3f", material.m_ambient[0], material.m_ambient[1], material.m_ambient[2], material.m_ambient[3]);
		printer.PushAttribute("Ambient", buffer);
		sprintf_s(buffer, 50, "%.3f %.3f %.3f %.3f", material.m_diffuse[0], material.m_diffuse[1], material.m_diffuse[2], material.m_diffuse[3]);
		printer.PushAttribute("Diffuse", buffer);
		sprintf_s(buffer, 50, "%.3f %.3f %.3f %.3f", material.m_emmisive[0], material.m_emmisive[1], material.m_emmisive[2], material.m_emmisive[3]);
		printer.PushAttribute("Emmisive", buffer);
		sprintf_s(buffer, 50, "%.3f %.3f %.3f %.3f", material.m_specular[0], material.m_specular[1], material.m_specular[2], material.m_specular[3]);
		printer.PushAttribute("Specular", buffer);
		printer.PushAttribute("Shininess", material.m_shininess);
		printer.PushAttribute("Shader", material.m_shader.getString().c_str());

		for (HashedString::Vector_t::iterator tex = material.m_textures.begin(); tex != material.m_textures.end(); ++tex)
		{
			printer.OpenElement("Texture");
			printer.PushAttribute("Name", (*tex).getString().c_str());
			printer.CloseElement();
		}
		printer.CloseElement();
#pragma endregion
#pragma region VertexContainer
		printer.OpenElement("VertexContainer");
		Pointer<IVertexContainer> vertex((*it)->getVertexContainer());

		std::vector<unsigned short>& indices(vertex->getIndices());
		const VertexDeclaration& declaration(vertex->getVertexDeclaration());
		unsigned vertexCount(vertex->getVerticeCount());
		unsigned char* vertexPtr((unsigned char*)(vertex->getVertexPointer()));
		bool isIBO(vertex->IsIBO());
		bool isVBO(vertex->IsVBO());
			
		printer.PushAttribute("VBO", isVBO);
		printer.PushAttribute("IBO", isIBO);
#pragma region Declaration
			printer.OpenElement("Declaration");
			printer.PushAttribute("Size", declaration.m_vertexSize);

			for (VertexType::Vector_t::const_iterator param = declaration.m_parameters.begin(); param != declaration.m_parameters.end(); ++param)
			{
				printer.OpenElement("Parameter");
				printer.PushAttribute("Offset", param->m_offset);
				printer.PushAttribute("Size", param->m_size);
				printer.PushAttribute("Parameter", param->m_parameter);
				printer.CloseElement();
			}

			printer.CloseElement();
#pragma endregion
#pragma region Vertices
			printer.OpenElement("Vertices");
			printer.PushAttribute("Count", vertexCount);

			unsigned char* ptr = vertexPtr;

			for (int i = 0; i <vertexCount*declaration.m_vertexSize; ++i)
			{
				printer.PushText(*(unsigned char*)(ptr));
				printer.PushText(" ");
				++ptr;
			}

			printer.CloseElement();
#pragma endregion
#pragma region Indices
			printer.OpenElement("Indices");
			printer.PushAttribute("Count", vertex->getIndiceCount());

			for (std::vector<unsigned short>::iterator index = indices.begin(); index != indices.end(); ++index)
			{
				printer.PushText(*index);
				printer.PushText(" ");
			}

			printer.CloseElement();
#pragma endregion
		printer.CloseElement();
#pragma endregion
		for (UniformCountInstructionMap_t::iterator uni = (*it)->getUniformInstructions().begin(); uni != (*it)->getUniformInstructions().begin(); ++uni)
		{
		}
		printer.CloseElement();
	}

	printer.CloseElement();
	
	return true;
}